home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 317_01 / g4sdecod.c < prev    next >
C/C++ Source or Header  |  1990-06-16  |  40KB  |  1,502 lines

  1. /*    $Id: g4sdecod.c 1.2 90/06/09 18:23:27 marking Exp $
  2.  *
  3.  NAME
  4.  *    g4sdecod.c -- decode group 4 data using nested if statements
  5.  *
  6.  TYPE
  7.  *    C procedures
  8.  *
  9.  SYNOPSIS
  10.  *    char    g4i_initialize (short image_width, short image_length);
  11.  *    char    g4i_decode (void);
  12.  *
  13.  DESCRIPTION
  14.  *    In order to acquire data from the image and to return run lengths and
  15.  *    new line information, these routines invoke procedures provided by the
  16.  *    caller. These caller-provided procedures are invoked throught pointers
  17.  *    which have been stuffed by the caller with the procedure addresses.
  18.  *    To acquire a new data byte, g4i_decode () calls (*p_g4i_next_byte) ().
  19.  *    To report the decoding of a black or white run, the routines
  20.  *    (*p_decode_black) () or (*p_decode_white) () are called.
  21.  *
  22.  RETURNS
  23.  *    Initialization always returns zero.
  24.  *
  25.  *    For decoding,
  26.  *        0    end of image reached
  27.  *        -1    on error (bad data)
  28.  *    The decode loop will be prematurely terminated if decode_return is
  29.  *    set to not zero, and the value of decode_return will be returned.
  30.  *    No code here does this, but it might be useful under certain
  31.  *    circumstances.
  32.  *
  33.  LEGAL
  34.  *    Copyright 1989, 1990 Michael P. Marking, Post Office Box 8039,
  35.  *    Scottsdale, Arizona 85252-8039. All rights reserved.
  36.  *
  37.  *    License is granted by the copyright holder to distribute and use this
  38.  *    code without payment of royalties or the necessity of notification as
  39.  *    long as this notice (all the text under "LEGAL") is included.
  40.  *
  41.  *    Reference: $Id: g4sdecod.c 1.2 90/06/09 18:23:27 marking Exp $
  42.  *
  43.  *    This program is offered without any warranty of any kind. It includes
  44.  *    no warranty of merchantability or fitness for any purpose. Testing and
  45.  *    suitability for any use are the sole responsibility of the user.
  46.  * 
  47.  HISTORY
  48.  *    $Log:    g4sdecod.c $
  49.  * Revision 1.2  90/06/09  18:23:27  marking
  50.  * clean up comments for release
  51.  * 
  52.  * Revision 1.1  90/05/01  02:00:00  marking
  53.  * Initial revision
  54.  * 
  55.  *
  56.  NOTES
  57.  *
  58.  PORTABILITY
  59.  *    Tested using Microsoft C 5.1. Some memory models may not work due to
  60.  *    the large decoding arrays.
  61.  *
  62.  *    There is a non-portable use of "global" variables in the file g3g4.h,
  63.  *    about which a minority of compilers will justifiably complain. Certain
  64.  *    variables are declared in g3g4.h without extern keywords. Strictly
  65.  *    speaking, they should be declared extern in all but one module, but
  66.  *    that would require complication of g3g4.h. If it gets past your
  67.  *    compiler and linker, you can probably ignore it.
  68.  *
  69.  SEE ALSO
  70.  *    g3tdecod.c -- decode group 3 image using tables
  71.  *    builddec.c -- build image decoding tables
  72.  *
  73.  INFORMATION
  74.  *    Although there is no support offered with this program, the author will
  75.  *    endeavor to correct errors. Updates will also be made available from
  76.  *    time to time.
  77.  *
  78.  *    Contact: Michael P. Marking, Post Office Box 8039, Scottsdale, Arizona
  79.  *    85252-8039 USA. Replies are not guaranteed to be swift. Beginning
  80.  *    July 1990, e-mail may be sent to uunet!ipel!marking.
  81.  *
  82.  *    Also beginning in July 1990, this code will be archived at the
  83.  *    ipel!phoenix BBS in file g3g4.zoo. The 24-hour telephone number
  84.  *    for 300/1200/2400 is (602)274-0462. When logging in, specify user
  85.  *    "public", system "bbs", and password "public".
  86.  *
  87.  *    This code is also available from the C Users Group in volume 317.
  88.  */
  89.  
  90. #include "g3g4.h"
  91.  
  92. /* #define TRACE 1 */
  93.  
  94. /* implementation limits: Due to the sizes of arrays and variables, and not
  95.    due to any restrictions in the algorithm, the following limits exist:
  96.      maximum number of pixels per row: 65533
  97.      maximum number of rows per image: none
  98.      maximum or minimum k-factor: none
  99.      maximum number of runs per row: 16382 white, 16382 black
  100.    To increase (or decrease) these limits, it will be necessary to play with
  101.    array and variable sizes.  On segmented machines (such as the 8086), a
  102.    different memory model may be necessary.  The algorithm itself has no
  103.    limits on image size or complexity, and the stack requirements are in-
  104.    sensitive to changes in these limits or to image complexity. */
  105.  
  106. #define EVEN 0
  107. #define ODD 1
  108.  
  109. static short a0, a1, a2, b0, b1, b2, bit_number, code_byte;
  110. static unsigned char color, current_row, mode;
  111. static unsigned short even_runs [32768], odd_runs [32768];
  112. static unsigned short even_index, odd_index;
  113. static short column_limit;
  114. static short row_number = 0;
  115.   /* Depending as current_row == EVEN or current_row == ODD, the runs of the
  116.      current row are represented in even_runs [] or odd_runs [].  The white
  117.      runs have even subscripts and the black runs have odd subscripts.  The
  118.      values of the array elements are the offsets of the beginnings of the
  119.      corresponding runs from the beginning of the row.  As defined by the
  120.      specification,
  121.     a0 is the reference or starting changing element on the coding line.
  122.         It may be considered the "current position".
  123.     a1 is the next changing element to the right of a0 on the coding line.
  124.     a2 is the next changing element to the right of a1 on the coding line.
  125.     b1 is the first changing element on the reference line to the right of
  126.         a0 and of opposite color to a0.
  127.     b2 is the next changing element to the right of b1 on the reference
  128.         line.
  129.      Furthermore,
  130.     b0 is the "previous" value of b1. 
  131.      Depending as current_row == EVEN or == ODD, even_index or odd_index is
  132.      the subscript of the entry in even_runs [] or odd_runs [] corresponding
  133.      to the run containing the current value of a0, and its counterpart cor-
  134.      responds to the run containing b1. */
  135.  
  136. static void new_row (void);
  137. static short decode_white_run (void);
  138. static short decode_black_run (void);
  139. static short decode_white_word (void);
  140. static short decode_black_word (void);
  141. static char next_bit (void);
  142. static short null_mode (void);
  143.  
  144. static char decode_return;
  145.  
  146. /* g4i_decode () successively invokes (*p_decode_next_byte) () for each byte of the
  147.    encoded image, and calls (*p_decode_white) () or (*p_decode_black) () as
  148.    required to return the image contents on a run-by-run basis. */
  149. char g4i_decode ()
  150. {
  151.   /* At the beginning of this routine, we are in the NULL mode, which is to
  152.      to say that no codewords are currently understood or digested.  The
  153.      variable bit_number has been initialized to zero, to indicate that the
  154.      next (first) codeword is to begin with bit zero of the next code byte.
  155.      This betrays an assumption that all images begin on byte boundaries, a
  156.      condition that can be changed by arranging for bit_number to be set
  157.      otherwise by g4i_initialize () or elsewhere. */
  158.   while (!decode_return)
  159.   {
  160.     mode = (unsigned char) null_mode ();
  161.     if (current_row == EVEN)
  162.     {
  163.       b0 = b1;
  164.       b1 = odd_runs [odd_index];
  165.       if ((b1 <= a0) && a0)
  166.       {
  167.     odd_index += 2;
  168.     b0 = odd_runs [odd_index - 1];
  169.     b1 = odd_runs [odd_index];
  170.       }
  171.       b2 = odd_runs [odd_index + 1];
  172.     }
  173.     else /* current_row == ODD */
  174.     {
  175.       b0 = b1;
  176.       b1 = even_runs [even_index];
  177.       if ((b1 <= a0) && a0)
  178.       {
  179.     even_index += 2;
  180.     b0 = even_runs [even_index - 1];
  181.     b1 = even_runs [even_index];
  182.       }
  183.       b2 = even_runs [even_index + 1];
  184.     }
  185.     #if defined (TRACE)
  186.       if (trace_flag)
  187.       {
  188.     if (current_row == EVEN)
  189.     {
  190.       printf ("\n ref_index=%hd b1=%hd b2=%hd a0=%hd curr[%hd]=%hd "
  191.         "color=%hd ",
  192.         odd_index, b1, b2, a0, even_index, even_runs [even_index],
  193.         (short) color);
  194.     }
  195.     else /* current_row == ODD */
  196.     {
  197.       printf ("\n ref_index=%hd b1=%hd b2=%hd a0=%hd curr[%hd]=%hd "
  198.         "color=%hd ",
  199.         even_index, b1, b2, a0, odd_index, odd_runs [odd_index],
  200.         (short) color);
  201.     }
  202.       }
  203.     #endif
  204.     switch (mode)
  205.     {
  206.       case PASS_MODE: /* skip (pass) two color changes on the previous row */
  207.     #if defined (TRACE)
  208.       if (trace_flag) printf (" P ");
  209.     #endif
  210.     if (color == WHITE) (*p_decode_white) ((short) (b2 - a0));
  211.     else /* color == BLACK */ (*p_decode_black) ((short) (b2 - a0));
  212.     a0 = b2;
  213.     if (current_row == EVEN)
  214.     {
  215.       odd_index += 2;
  216.       b1 = odd_runs [odd_index];
  217.     }
  218.     else /* curren